package com.sinocare.project.maintenance.config;

import com.sinocare.project.maintenance.realm.MyRealm;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.config.ShiroConfiguration;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 用来整合Shiro框架相关的配置类
 */
@Configuration
public class ShiroConfig {
    //1. 创建ShiroFilter 负责拦截所有请求
//    @Bean
//    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) {
//        //参数调用下面的getDefaultWebSecurityManager
//        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
////        //TODO：此处要加入权限控制（见下小节）
////        Map<String, String> map = new LinkedHashMap<String, String>();
////        map.put("/", "anon");
////        map.put("/user/login", "anon");
////        map.put("/index", "user"); //表示记住我可以访问的url（已认证也可以访问）
////        //map.put("/login","perms[sys:c:save]"); //表示必须具体sys:c:save权限才能访问
////        map.put("/exit", "logout");
////        map.put("/**", "authc");
////        //没有权限默认跳转的路径
////        shiroFilterFactoryBean.setUnauthorizedUrl("/toLogin");
////        //登录成功默认跳转的路径
////        shiroFilterFactoryBean.setSuccessUrl("/toHome");
////        //默认登录界面路径
////        shiroFilterFactoryBean.setLoginUrl("/toLogin");
////        //配置认证和授权规则
////        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
//        //给filter注入安全管理器
//        return shiroFilterFactoryBean;
//    }

    //2. 配置核心安全事务管理器
//    @Bean
//    public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm) {
//        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
//        //给安全管理器设置
//        defaultWebSecurityManager.setRealm(realm);
//        return defaultWebSecurityManager;
//    }
//
//    //3. 创建自定义realm
//    @Bean
//    public Realm getRealm() {
//        return new MyRealm();
//    }

        private static final Logger log = LoggerFactory.getLogger(ShiroConfiguration.class);

        @Bean
        public EhCacheManager getEhCacheManager() {
            EhCacheManager em = new EhCacheManager();
            em.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
            return em;
        }


        @Bean(name = "lifecycleBeanPostProcessor")
        public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
            return new LifecycleBeanPostProcessor();
        }


        /**
         * 加密器：这样一来数据库就可以是密文存储，为了演示我就不开启了
         *
         * @return HashedCredentialsMatcher
         */
//    @Bean
//    public HashedCredentialsMatcher hashedCredentialsMatcher() {
//        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
//        //散列算法:这里使用MD5算法;
//        hashedCredentialsMatcher.setHashAlgorithmName("md5");
//        //散列的次数，比如散列两次，相当于 md5(md5(""));
//        hashedCredentialsMatcher.setHashIterations(2);
//        return hashedCredentialsMatcher;
//    }


        @Bean
        public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
            DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
            autoProxyCreator.setProxyTargetClass(true);
            return autoProxyCreator;
        }

        @Bean(name = "myRealm")
        public MyRealm authRealm(EhCacheManager cacheManager) {
            MyRealm authRealm = new MyRealm();
            authRealm.setCacheManager(cacheManager);
            return authRealm;
        }

        @Bean(name = "securityManager")
        public DefaultWebSecurityManager getDefaultWebSecurityManager(MyRealm myRealm) {
            DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
            defaultWebSecurityManager.setRealm(myRealm);
            // <!-- 用户授权/认证信息Cache, 采用EhCache 缓存 -->
            defaultWebSecurityManager.setCacheManager(getEhCacheManager());
            return defaultWebSecurityManager;
        }

        @Bean
        public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(
                DefaultWebSecurityManager securityManager) {
            AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
            advisor.setSecurityManager(securityManager);
            return advisor;
        }

        /**
         * ShiroFilter<br/>
         * 注意这里参数中的 StudentService 和 IScoreDao 只是一个例子，因为我们在这里可以用这样的方式获取到相关访问数据库的对象，
         * 然后读取数据库相关配置，配置到 shiroFilterFactoryBean 的访问规则中。实际项目中，请使用自己的Service来处理业务逻辑。
         *
         * @param securityManager 安全管理器
         * @return ShiroFilterFactoryBean
         */
        @Bean(name = "shiroFilter")
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            // 必须设置 SecurityManager
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            // 如果不设置默认会自动寻找Web工程根目录下的"/login"页面
            shiroFilterFactoryBean.setLoginUrl("/login.html");
            // 登录成功后要跳转的连接
            shiroFilterFactoryBean.setSuccessUrl("/index.html");
//            shiroFilterFactoryBean.setUnauthorizedUrl("/denied");
            loadShiroFilterChain(shiroFilterFactoryBean);
            return shiroFilterFactoryBean;
        }

        /**
         * 加载shiroFilter权限控制规则（从数据库读取然后配置）
         */
        private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean) {
            /////////////////////// 下面这些规则配置最好配置到配置文件中 ///////////////////////
            // TODO 重中之重啊，过滤顺序一定要根据自己需要排序
            Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
//            // 需要验证的写 authc 不需要的写 anon
//            filterChainDefinitionMap.put("/sncUserLogin/login", "anon");
//            filterChainDefinitionMap.put("/install", "anon");
//            filterChainDefinitionMap.put("/hello", "anon");
//             anon：它对应的过滤器里面是空的,什么都没做
            log.info("##################从数据库读取权限规则，加载到shiroFilter中##################");

            // 不用注解也可以通过 API 方式加载权限规则
//            Map<String, String> permissions = new LinkedHashMap<>();
//            permissions.put("/users/find", "perms[user:find]");
//            filterChainDefinitionMap.putAll(permissions);
//            filterChainDefinitionMap.put("/**", "authc");
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        }













}